package com.ruoyi.coupon.service.impl;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.coupon.config.RabbitMQConfig;
import com.ruoyi.coupon.domain.CouponRecord;
import com.ruoyi.coupon.domain.CouponTask;
import com.ruoyi.coupon.domain.JsonData;
import com.ruoyi.coupon.enums.BizCodeEnum;
import com.ruoyi.coupon.enums.CouponStateEnum;
import com.ruoyi.coupon.enums.ProductOrderStateEnum;
import com.ruoyi.coupon.enums.StockTaskStateEnum;
import com.ruoyi.coupon.exception.BizException;
import com.ruoyi.coupon.feign.ProductOrderFeignSerivce;
import com.ruoyi.coupon.mapper.CouponRecordMapper;
import com.ruoyi.coupon.mapper.CouponTaskMapper;
import com.ruoyi.coupon.model.CouponUseVO;
import com.ruoyi.coupon.mq.CouponRecordMessage;
import com.ruoyi.coupon.request.LockCouponRecordRequest;
import com.ruoyi.coupon.service.ICouponRecordService;
import com.ruoyi.coupon.service.ICouponTaskService;
import com.ruoyi.coupon.utils.RedisIdWorker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;


/**
 * couponrecordService业务层处理
 *
 * @author 林道敬
 * @date 2025-01-02
 */
@Service
@Slf4j
public class CouponRecordServiceImpl extends ServiceImpl<CouponRecordMapper, CouponRecord> implements ICouponRecordService
{
    @Autowired
    private CouponRecordMapper couponRecordMapper;
    @Autowired
    private ICouponTaskService couponTaskService;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMQConfig rabbitMQConfig;
    @Autowired
    private CouponTaskMapper couponTaskMapper;
    @Autowired
    ProductOrderFeignSerivce productOrderFeignSerivce;

    /**
     * 查询couponrecord
     *
     * @param id couponrecord主键
     * @return couponrecord
     */
    @Override
    public CouponRecord selectCouponRecordById(String id)
    {
        return couponRecordMapper.selectCouponRecordById(id);
    }

    /**
     * 查询couponrecord列表
     *
     * @param couponRecord couponrecord
     * @return couponrecord
     */
    @Override
    public List<CouponRecord> selectCouponRecordList(CouponRecord couponRecord)
    {
        return couponRecordMapper.selectCouponRecordList(couponRecord);
    }

    /**
     * 新增couponrecord
     *
     * @param couponRecord couponrecord
     * @return 结果
     */
    @Override
    public int insertCouponRecord(CouponRecord couponRecord)
    {
        couponRecord.setCreateTime(DateUtils.getNowDate());
        return couponRecordMapper.insertCouponRecord(couponRecord);
    }

    /**
     * 修改couponrecord
     *
     * @param couponRecord couponrecord
     * @return 结果
     */
    @Override
    public int updateCouponRecord(CouponRecord couponRecord)
    {
        return couponRecordMapper.updateCouponRecord(couponRecord);
    }

    /**
     * 批量删除couponrecord
     *
     * @param ids 需要删除的couponrecord主键
     * @return 结果
     */
    @Override
    public int deleteCouponRecordByIds(String[] ids)
    {
        return couponRecordMapper.deleteCouponRecordByIds(ids);
    }

    /**
     * 删除couponrecord信息
     *
     * @param id couponrecord主键
     * @return 结果
     */
    @Override
    public int deleteCouponRecordById(String id)
    {
        return couponRecordMapper.deleteCouponRecordById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public JsonData lockCouponRecords(LockCouponRecordRequest recordRequest) {
        String orderOutTradeNo = recordRequest.getOrderOutTradeNo();
        List<Long> lockCouponRecordIds = recordRequest.getLockCouponRecordIds();
        int updateRows = couponRecordMapper.lockUseStateBatch(1l, CouponStateEnum.USED.name(),lockCouponRecordIds);
        List<CouponTask> couponTaskDOList =  lockCouponRecordIds.stream().map(obj->{
            CouponTask couponTaskDO = new CouponTask();
            couponTaskDO.setCreateTime(new Date());
            couponTaskDO.setOutTradeNo(orderOutTradeNo);
            couponTaskDO.setCouponRecordId(obj);
            couponTaskDO.setLockState(StockTaskStateEnum.LOCK.name());
            return couponTaskDO;
        }).collect(Collectors.toList());

        boolean isSave = couponTaskService.saveBatch(couponTaskDOList);
        log.info("优惠券记录锁定updateRows={}",updateRows);
        log.info("新增优惠券记录task insertRows={}",isSave);
        if(isSave){
            //发送延迟消息
            for(CouponTask couponTask : couponTaskDOList){
                CouponRecordMessage couponRecordMessage = new CouponRecordMessage();
                couponRecordMessage.setOutTradeNo(orderOutTradeNo);
                couponRecordMessage.setTaskId(couponTask.getId());
                rabbitTemplate.convertAndSend(rabbitMQConfig.getEventExchange(),rabbitMQConfig.getCouponReleaseDelayRoutingKey(),couponRecordMessage);
                log.info("优惠券锁定消息发送成功:{}",couponRecordMessage.toString());
            }
            return JsonData.buildSuccess();
        }else {

            throw new BizException(BizCodeEnum.COUPON_RECORD_LOCK_FAIL);
        }
    }


    /**
     * 解锁优惠券记录
     * 1）查询task工作单是否存在
     * 2) 查询订单状态
     * @param recordMessage
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public boolean releaseCouponRecord(CouponRecordMessage recordMessage) {
        //查询下task是否存
        CouponTask taskDO = couponTaskMapper.selectOne(new QueryWrapper<CouponTask>().eq("id",recordMessage.getTaskId()));

        if(taskDO==null){
            log.warn("工作单不存，消息:{}",recordMessage);
            return true;
        }

        //lock状态才处理
        if(taskDO.getLockState().equalsIgnoreCase(StockTaskStateEnum.LOCK.name())){

            //查询订单状态
            JsonData jsonData = productOrderFeignSerivce.queryProductOrderState(recordMessage.getOutTradeNo());
            if(jsonData.getCode()==0){
                //正常响应，判断订单状态
                String state = jsonData.getData().toString();
                if(ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)){
                    //状态是NEW新建状态，则返回给消息队列重新投递
                    log.warn("订单状态是NEW,返回给消息队列，重新投递:{}",recordMessage);
                    return false;
                }

                //如果是已经支付
                if(ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)){
                    //如果已经支付，修改task状态为finish
                    taskDO.setLockState(StockTaskStateEnum.FINISH.name());
                    couponTaskMapper.update(taskDO,new QueryWrapper<CouponTask>().eq("id",recordMessage.getTaskId()));
                    log.info("订单已经支付，修改库存锁定工作单FINISH状态:{}",recordMessage);
                    return true;
                }
            }

            //订单不存在，或者订单被取消，确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW
            log.warn("订单不存在，或者订单被取消，确认消息,修改task状态为CANCEL,恢复优惠券使用记录为NEW,message:{}",recordMessage);
            taskDO.setLockState(StockTaskStateEnum.CANCEL.name());

            couponTaskMapper.update(taskDO,new QueryWrapper<CouponTask>().eq("id",recordMessage.getTaskId()));
            //恢复优惠券记录是NEW状态
            couponRecordMapper.updateState(taskDO.getCouponRecordId(),CouponStateEnum.NEW.name());

            return true;
        }else {
            log.warn("工作单状态不是LOCK,state={},消息体={}",taskDO.getLockState(),recordMessage);
            return true;
        }

    }

    @Override
    @Transactional
    public R useCoupon(CouponUseVO couponUseVO) {
        if(couponUseVO != null){
            BigDecimal totalPrice = new BigDecimal( couponUseVO.getTotalPrice());
            BigDecimal priceNumber = BigDecimal.ZERO;
            for(String couponid: couponUseVO.getCouponIds()){
                CouponRecord couponRecord = couponRecordMapper.selectById(couponid);
                BigDecimal result =totalPrice.subtract(couponRecord.getConditionPrice());
                if(result.compareTo(BigDecimal.ZERO)>=0){
                    priceNumber = priceNumber.add(couponRecord.getPrice());
                }else {
                    return R.fail("使用优惠卷失败！！！");
                }
            }
            BigDecimal result = totalPrice.subtract(priceNumber);
            return R.ok(result.toString());
        }
        return R.fail("使用优惠卷失败！！！");
    }
}
